package com.lft.juc02.producterconsumer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Function: 		A {@code PC} 线程之间的通信问题：生产者与消费者.<br/>
 * Reason:   		线程交替执行.<br/>
 * A B 操作现一个变量 num = 0
 * A num + 1
 * B num - 1
 * Date:            2021-01-29 15:51<br/>
 * <p>
 * Class Name:      PC<br/>
 * Package Name:    com.lft.juc02.producterconsumer<br/>
 * @author Laifengting / E-mail:laifengting@foxmail.com
 * @version 1.0.0
 * @since JDK 8
 */
public class PC_JUC_Precise {
	public static void main(String[] args) {
		Date3 date = new Date3();
		new Thread(() -> {for (int i = 0; i < 10; i++)date.printA();}).start();
		new Thread(() -> {for (int i = 0; i < 10; i++)date.printB();}).start();
		new Thread(() -> {for (int i = 0; i < 10; i++)date.printC();}).start();
		new Thread(() -> {for (int i = 0; i < 10; i++)date.printD();}).start();

	}
}

/**
 * 资源类——数据
 */
class Date3 {
	private Lock lock = new ReentrantLock();
	Condition conditionA = lock.newCondition();
	Condition conditionB = lock.newCondition();
	Condition conditionC = lock.newCondition();
	Condition conditionD = lock.newCondition();
	/**
	 * 1打印A 2打印B 3打印C 4打印D
	 */
	private int number = 1;
	
	public void printA() {
		lock.lock();
		try {
			// 业务，判断 ——> 执行 ——> 通知
			while (number != 1) {
				conditionA.await();
			}
			System.out.println("A" + " ——> " + number);
			number = 2;
			conditionB.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void printB() {
		lock.lock();
		try {
			// 业务，判断 ——> 执行 ——> 通知
			while (number != 2) {
				conditionB.await();
			}
			System.out.println("B" + " ——> " + number);
			number = 3;
			conditionC.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void printC() {
		lock.lock();
		try {
			// 业务，判断 ——> 执行 ——> 通知
			while (number != 3) {
				conditionC.await();
			}
			System.out.println("C" + " ——> " + number);
			number = 4;
			conditionD.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	public void printD() {
		lock.lock();
		try {
			// 业务，判断 ——> 执行 ——> 通知
			while (number != 4) {
				conditionD.await();
			}
			System.out.println("D" + " ——> " + number);
			number = 1;
			conditionA.signal();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
}
